﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;

/// <summary>
/// 플로우 형식의 런처.
/// </summary>
public class wsLauncherFlow : MonoBehaviour
{
	/// <summary>
	/// 한 화면에 보여질 아이템의 개수.
	/// </summary>
	public int maxViewCount = 9;
	/// <summary>
	/// 중앙 아이템의 인덱스.
	/// </summary>
	public int startIndex = 0;
	/// <summary>
	/// 아이템간의 가로 간격.
	/// </summary>
	public float horizonSpace = 2.0f;
	/// <summary>
	/// 아이템간의 세로 간격.
	/// </summary>
	public float verticalSpace = 2.0f;
	/// <summary>
	/// 중앙 아이템과 좌우 아이템간의 거리.
	/// </summary>
	public float distFromCenter = 1.0f;
	/// <summary>
	/// 아이템을 변경하는데 걸리는 시간.
	/// </summary>
	public float timeInTo = 4.0f;
	/// <summary>
	/// 연속 키 입력 간격.
	/// </summary>
	public float inputInterval = 0.2f;

	/// <summary>
	/// 중앙 아이템이 바라보는 지점.
	/// </summary>
	public Transform lookAtCurrent;
	/// <summary>
	/// 좌우 아이템이 바라보는 지점.
	/// </summary>
	public Transform lookAtOthers;
	/// <summary>
	/// 선택 아이템이 이동할 지점.
	/// </summary>
	public Transform selectedPosition;

	/// <summary>
	/// 아이템 리스트.
	/// </summary>
	public List<wsLauncherItem> itemList;

	/// <summary>
	/// 키 입력을 받은 시간.
	/// </summary>
	private float inputTimer = 0;
	/// <summary>
	/// 왼쪽 화살표키 입력 여부.
	/// </summary>
	private bool leftKeyDown = false;
	/// <summary>
	/// 오른쪽 화살표키 입력 여부.
	/// </summary>
	private bool rightKeyDown = false;

	/// <summary>
	/// 화면에 나타나는 아이템들의 시작 인덱스.
	/// </summary>
	private int firstIndex = 0;
	/// <summary>
	/// 화면에 나타나는 아이템들의 마지막 인덱스.
	/// </summary>
	private int lastIndex = 0;
	/// <summary>
	/// 화면의 중앙에 나타나는 아이템의 인덱스.
	/// </summary>
	private int currentIndex = 0;
	/// <summary>
	/// 중앙 아이템이 선택되었는지 여부.
	/// </summary>
	private bool selectItem = false;

	void Start()
	{
		if (maxViewCount % 2 != 1)
			Debug.LogError("maxViewCount is only allowed odd number.");

		currentIndex = startIndex;

		UpdateItem(true);
	}

	void Update()
	{
		UpdateMouse();
		UpdateKeyboard(inputInterval);
		UpdatePosition(true);
	}

	void UpdateMouse()
	{
		if (Input.GetMouseButtonDown(wsMouse.LEFT))
		{
			Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
			RaycastHit hitInfo = new RaycastHit();

			int clickedIndex = -1;
			float clickedPosZ = -1;

			for (int i = firstIndex; i <= lastIndex; i++)
			{
				Collider col = itemList[i].ModelCollider;

				if (col.Raycast(ray, out hitInfo, 100))
				{
					if (clickedIndex < 0)
					{
						clickedIndex = i;
						clickedPosZ = hitInfo.point.z;
					}
					else
					{
						if (hitInfo.point.z < clickedPosZ)
						{
							clickedIndex = i;
							clickedPosZ = hitInfo.point.z;
						}
					}
				}
			}

			if (clickedIndex > 0)
			{
				if (clickedIndex == currentIndex)
				{
					SelectItemToggle();
				}
				else
				{
					CurrentItem(clickedIndex);
				}
			}
		}
	}

	void UpdateKeyboard(float interval)
	{
		if (Input.GetKeyUp(KeyCode.LeftArrow))
		{
			leftKeyDown = false;
			inputTimer = 0;
		}

		if (Input.GetKeyUp(KeyCode.RightArrow))
		{
			rightKeyDown = false;
			inputTimer = 0;
		}

		if (Input.GetKey(KeyCode.LeftArrow))
		{
			if (leftKeyDown)
			{
				inputTimer += Time.deltaTime;
				if (inputTimer > inputInterval)
				{
					CurrentItem(currentIndex - 1);
					inputTimer = 0;
				}
			}
		}

		if (Input.GetKey(KeyCode.RightArrow))
		{
			if (rightKeyDown)
			{
				inputTimer += Time.deltaTime;
				if (inputTimer > inputInterval)
				{
					CurrentItem(currentIndex + 1);
					inputTimer = 0;
				}
			}
		}

		if (Input.GetKeyDown(KeyCode.LeftArrow))
		{
			leftKeyDown = true;

			CurrentItem(currentIndex - 1);
		}

		if (Input.GetKeyDown(KeyCode.RightArrow))
		{
			rightKeyDown = true;

			CurrentItem(currentIndex + 1);
		}

		if (Input.GetKeyDown(KeyCode.Return))
		{
			SelectItemToggle();
		}
	}

	void SelectItemToggle()
	{
		selectItem = !selectItem;
	}

	void CurrentItem(int index)
	{
		currentIndex = index;

		if (currentIndex < 0)
			currentIndex = 0;

		if (currentIndex > itemList.Count - 1)
			currentIndex = itemList.Count - 1;

		UpdateItem(false);
	}

	void UpdateItem(bool hiddenItemStartFromZero)
	{
		firstIndex = currentIndex - maxViewCount / 2;
		if (firstIndex < 0)
			firstIndex = 0;

		lastIndex = currentIndex + maxViewCount / 2;
		if (lastIndex > itemList.Count - 1)
			lastIndex = itemList.Count - 1;

		for (int i = 0; i < itemList.Count; i++)
		{
			if (firstIndex <= i && i <= lastIndex)
			{
				int position = i - currentIndex;

				if (itemList[i].EnableItem == false)
				{
					itemList[i].EnableItem = true;

					if (hiddenItemStartFromZero)
					{
						itemList[i].transform.position = Vector3.zero;
					}
					else
					{
						if (i < currentIndex)
						{
							itemList[i].transform.position = GetPosition(position - 1);
						}
						else
						{
							itemList[i].transform.position = GetPosition(position + 1);
						}
					}
				}

				if (i == currentIndex)
				{
					itemList[i].LookAt.target = lookAtCurrent;
				}
				else
				{
					itemList[i].LookAt.target = lookAtOthers;
				}
			}
			else
			{
				itemList[i].EnableItem = false;
			}
		}
	}

	void UpdatePosition(bool smooth)
	{
		for (int i = firstIndex; i <= lastIndex; i++)
		{
			int position = i - currentIndex;
			itemList[i].EnableItem = true;

			if (smooth)
			{
				if (selectItem && i == currentIndex)
				{
					itemList[i].transform.position = Vector3.Lerp(itemList[i].transform.position,
																	GetSelectedPosition(),
																	Time.deltaTime * timeInTo);

				}
				else
				{
					itemList[i].transform.position = Vector3.Lerp(itemList[i].transform.position,
																	GetPosition(position),
																	Time.deltaTime * timeInTo);

				}
			}
			else
			{
				if (selectItem && i == currentIndex)
				{
					itemList[i].transform.position = GetSelectedPosition();
				}
				else
				{
					itemList[i].transform.position = GetPosition(position);
				}
			}
		}
	}

	Vector3 GetPosition(int position)
	{
		Vector3 center = Vector3.zero;

		center.x = horizonSpace * position;
		center.z = verticalSpace * wsMath.Abs(position);

		if (position > 0)
		{
			center.x += distFromCenter;
		}
		else if (position < 0)
		{
			center.x -= distFromCenter;
		}

		return center;
	}

	Vector3 GetSelectedPosition()
	{
		//return new Vector3(0, 0, -5);		
		return selectedPosition.position;
	}
}
